package com.tbit.uqbike.service.rpcservice.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.tbit.uqbike.constant.UserConstant;
import com.tbit.uqbike.object.business.User2Machine;
import com.tbit.uqbike.object.pojo.Account;
import com.tbit.uqbike.object.pojo.HolderAccountBound;
import com.tbit.uqbike.object.pojo.Machine;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.service.business.HolderAccountBoundService;
import com.tbit.uqbike.service.rpcservice.PurviewService;
import com.tbit.uqbike.webmanager.dao.core.AccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author MyWin E-mail:335918956@qq.com
 * @version 1.0
 * @createTime 2019-12-06 14:35
 */
@Service
public class PurviewServiceImpl implements PurviewService {
    @Autowired
    private AccountDao accountDao;
    @Autowired
    private HolderAccountBoundService holderAccountBoundService;

    private List<Integer> account2ids(List<Account> accounts) {
        List<Integer> list = new LinkedList<>();
        for (Account item : accounts) {
            list.add(item.getAccountId());
        }
        return list;
    }

    @Override
    public boolean purviewCheck(Integer operateType, Integer operateId, Integer objType, Integer objId) {
        Account opAcc = accountDao.getByAccountId(operateId);
        Account objAcc = accountDao.getByAccountId(objId);
        return purviewCheck(opAcc, objAcc);
    }

    @Override
    public boolean purviewCheck(Integer operateId, Integer objId) {
        Account opAcc = accountDao.getByAccountId(operateId);
        Account objAcc = accountDao.getByAccountId(objId);
        return purviewCheck(opAcc, objAcc);
    }

    @Override
    public boolean purviewCheck(Account opAcc, Account objAcc) {
        if (opAcc == null) {
            return false;
        } else {
            if (null == objAcc || objAcc.getAccountId() == -1) {
                return true;
            } else {
                Integer operateType = opAcc.getType();
                Integer objType = objAcc.getType();
                Integer operateId = opAcc.getAccountId();
                Integer objId = objAcc.getAccountId();
                if (Objects.equals(operateType, objType)) {
                    if (Objects.equals(operateId, objId)) {
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    if (Objects.equals(operateType, UserConstant.USER_ADMIN)) {
                        return true;
                    } else {
                        Map<String, Object> map = new HashMap<>();
                        if (Objects.equals(opAcc.getType(), UserConstant.USER_ADMIN)) {
                            // 不加过滤
                        } else if (Objects.equals(opAcc.getType(), UserConstant.USER_BRAND)) {
                            // 加入pid过滤
                            map.put("bid", opAcc.getAccountId());
                        } else if (Objects.equals(opAcc.getType(), UserConstant.USER_FRANCHISEE)) {
                            // 加入fid过滤
                            map.put("fid", opAcc.getAccountId());
                        } else if (Objects.equals(opAcc.getType(), UserConstant.USER_AGENT)) {
                            // 加入aid过滤
                            map.put("aid", opAcc.getAccountId());
                        } else {
                            return false;
                        }
                        List<Account> accountList = accountDao.getAccountTree(map);
                        for (Account item : accountList) {
                            if (Objects.equals(item.getAccountId(), objId)) {
                                return true;
                            }
                        }
                    }
                    return false;
                }
            }
        }
    }

    @Override
    public boolean purviewCheck(Integer operateId, Machine machine) {
        Account opAcc = accountDao.getByAccountId(operateId);
        return purviewCheck(opAcc, machine);
    }

    @Override
    public boolean purviewCheck(Account opAcc, Machine machine) {
        Account objAcc = accountDao.getByAccountId(machine.getAccountId());
        return purviewCheck(opAcc, objAcc);
    }

    @Override
    public User2Machine getUser2Machine(LoginInfo info) {
        Integer accountId = info.id;
        User2Machine data = new User2Machine();
        data.account = accountDao.getByAccountId(accountId);
        if (data.account == null) {
            return data;
        }

        Map<String, Object> map = new HashMap<>();
        Integer operateType = data.account.getType();
        List<HolderAccountBound> holderAccountBoundList = holderAccountBoundService.getByAccountUserId(info.getAccountUserId());
        if (CollUtil.isNotEmpty(holderAccountBoundList)) {
            String accountIds = holderAccountBoundList.stream().map(HolderAccountBound::getAccountId).map(String::valueOf).collect(Collectors.joining(","));
            map.put("accountIds", accountIds);
        } else if (Objects.equals(operateType, UserConstant.USER_ADMIN)) {
        }
        else if (Objects.equals(operateType, UserConstant.USER_BRAND)) {
            map.put("bid", accountId);
        } else if (Objects.equals(operateType, UserConstant.USER_AGENT)) {
            map.put("aid", accountId);
        } else if (Objects.equals(operateType, UserConstant.USER_FRANCHISEE)) {
            map.put("fid", accountId);
        } else {
            return data;
        }
        data.machines = accountDao.getMachineShortInfoByAccountId(map);
        return data;
    }

    @Override
    public List<Integer> filterAgent(Account opAcc, List<Integer> accountIds) {
        if (null == opAcc || accountIds.isEmpty()) {
            return new LinkedList<>();
        }
        Map<String, Object> map = new HashMap<>();
        map.put("accountIds", accountIds);
        map.put("type", UserConstant.USER_AGENT);
        List<Account> accounts = null;
        if (Objects.equals(opAcc.getType(), UserConstant.USER_ADMIN)) {
            // 不加过滤
        } else if (Objects.equals(opAcc.getType(), UserConstant.USER_BRAND)) {
            // 加入pid过滤
            map.put("bid", opAcc.getAccountId());
        } else if (Objects.equals(opAcc.getType(), UserConstant.USER_FRANCHISEE)) {
            // 加入fid过滤
            map.put("fid", opAcc.getAccountId());
        } else if (Objects.equals(opAcc.getType(), UserConstant.USER_AGENT)) {
            // 加入aid过滤
            map.put("aid", opAcc.getAccountId());
        } else {
            return new LinkedList<>();
        }
        if (null == accounts) {
            accounts = accountDao.getAccountByIdExTypePidAid(map);
            if (Objects.equals(opAcc.getType(), UserConstant.USER_BRAND)) {
                Account byAccountId = accountDao.getByAccountId(opAcc.getAccountId());
                accounts.add(0, byAccountId);
            }
        }
        return account2ids(accounts);
    }

    @Override
    public List<Integer> getAgentList(Account opAcc) {
        if (null == opAcc) {
            return new LinkedList<>();
        }
        Map<String, Object> map = new HashMap<>();
        map.put("type", UserConstant.USER_AGENT);
        List<Account> accounts = null;
        if (Objects.equals(opAcc.getType(), UserConstant.USER_ADMIN)) {
            // 不加过滤
        } else if (Objects.equals(opAcc.getType(), UserConstant.USER_BRAND)) {
            // 加入pid过滤
            map.put("bid", opAcc.getAccountId());
        } else if (Objects.equals(opAcc.getType(), UserConstant.USER_FRANCHISEE)) {
            // 加入fid过滤
            map.put("fid", opAcc.getAccountId());
        } else if (Objects.equals(opAcc.getType(), UserConstant.USER_AGENT)) {
            // 加入aid过滤
            map.put("aid", opAcc.getAccountId());
        } else {
            return new LinkedList<>();
        }
        if (null == accounts) {
            accounts = accountDao.getAccountByIdExTypePidAid(map);
        }
        return account2ids(accounts);
    }

    @Override
    public List<Integer> filterFranchisee(Account opAcc, List<Integer> accountIds) {
        if (null == opAcc || accountIds.isEmpty()) {
            return new LinkedList<>();
        }
        Map<String, Object> map = new HashMap<>();
        map.put("accountIds", accountIds);
        map.put("type", UserConstant.USER_FRANCHISEE);
        List<Account> accounts = null;
        if (Objects.equals(opAcc.getType(), UserConstant.USER_ADMIN)) {
            // 不加过滤
        } else if (Objects.equals(opAcc.getType(), UserConstant.USER_BRAND)) {
            map.put("pid", opAcc.getAccountId());
        } else if (Objects.equals(opAcc.getType(), UserConstant.USER_FRANCHISEE)) {
            // 加入aid过滤
            map.put("aid", opAcc.getAccountId());
        } else {
            return new LinkedList<>();
        }
        if (null == accounts) {
            accounts = accountDao.getAccountByIdExTypePidAid(map);
        }
        return account2ids(accounts);
    }


    @Override
    public Map<Integer, Boolean> purviewCheckV2(Integer loginUserId, Set<Integer> machineAIds) {
        if (CollectionUtil.isNotEmpty(machineAIds) &&
                machineAIds.size() == 1 && machineAIds.contains(loginUserId)){
            return getAllCheck(machineAIds,true);
        }
        Account opAcc = accountDao.getByAccountId(loginUserId);
//        List<Account> objAccList = accountDao.getByAccountIds(new ArrayList<>(machineAIds));
        return purviewCheckV2(opAcc, machineAIds);
    }

    public Map<Integer, Boolean> purviewCheckV2(Account opAcc, Set<Integer> machineAIds) {
        if (CollectionUtil.isEmpty(machineAIds)) {
            return getAllCheck(machineAIds,true);
        }
        if (Objects.isNull(opAcc)){
            return getAllCheck(machineAIds,true);
        }
        Integer operateType = opAcc.getType();
//        Integer objType = objAcc.getType();
//        Integer operateId = opAcc.getAccountId();
//        Integer objId = objAcc.getAccountId();
        Map<Integer, Boolean> machineAccIdCheckMap = new HashMap<>();

        if (Objects.equals(operateType, UserConstant.USER_ADMIN)) {
            return getAllCheck(machineAIds,true);
        } else {
            Map<String, Object> map = new HashMap<>();
            if (Objects.equals(opAcc.getType(), UserConstant.USER_ADMIN)) {
                // 不加过滤
            } else if (Objects.equals(opAcc.getType(), UserConstant.USER_BRAND)) {
                // 加入pid过滤
                map.put("bid", opAcc.getAccountId());
            } else if (Objects.equals(opAcc.getType(), UserConstant.USER_FRANCHISEE)) {
                // 加入fid过滤
                map.put("fid", opAcc.getAccountId());
            } else if (Objects.equals(opAcc.getType(), UserConstant.USER_AGENT)) {
                // 加入aid过滤
                map.put("aid", opAcc.getAccountId());
            } else {
                return getAllCheck(machineAIds,false);
            }
            List<Account> accountList = accountDao.getAccountTree(map);
            if (CollectionUtil.isNotEmpty(accountList)){
                return getAllCheck(machineAIds,false);
            }
            List<Integer> opAccountIdList = accountList.stream().map(account -> account.getAccountId()).collect(Collectors.toList());
            for (Integer machineAId : machineAIds) {
                machineAccIdCheckMap.put(machineAId,opAccountIdList.contains(machineAId));
            }
        }
        return machineAccIdCheckMap;
    }

    public Map<Integer, Boolean> getAllCheck(Set<Integer> machineAIds,Boolean b){
        Map<Integer, Boolean> machineAccIdCheckMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(machineAIds)){
            for (Integer aId : machineAIds) {
                machineAccIdCheckMap.put(aId, b);
            }
        }
        return machineAccIdCheckMap;
    }

    @Override
    public boolean purviewCheck(Integer operateId, List<Integer> objId) {
        Account opAcc = accountDao.getByAccountId(operateId);
        if (!CollectionUtils.isEmpty(objId)){
            for (Integer integer : objId) {
                Account account = accountDao.getByAccountId(integer);
                if (!purviewCheck(opAcc, account)){
                    return false;
                }
            }
        }
        return true;
    }
}
